
#include "usart.h"
#include "timer.h"
#include "IO.h"
#include "frame.h"

#define NULL 0
#define USE_USART &AVR32_USART1


void initTimer(void){

	timerList = (element*)malloc(sizeof(element));
	dupaTimer("Timer initialization\n");
	timerList->ID=NULL;
	timerList->next=NULL;
	nrEl = 1;
	tick = 1;

}


__attribute__((__interrupt__)) void timerHandler(void){

	element *wsk;
	wsk = timerList;
	while(wsk != NULL){
		if(wsk->accTime == tick){
			if (wsk->Off != 1){
				wsk->fun();
				wsk->accTime = (tick + wsk->time ) % MAX_TICK;
				if( wsk->Once == 1 ) wsk->Off = 1;
				dupaTimer("Check timer ID - ");
				dupaTimerInt(wsk->ID);
			}
		}
		wsk = wsk->next;

	}

	//dupaTimerInt(tick);
	tick++;

	if (tick == MAX_TICK) tick = 0;
	tc_read_sr(&AVR32_TC, TC_CHANNEL);

}

////////////////////////////////////////////
////////////////////////////////////////////
////////////////////////////////////////////


int setTimer( void (*fun)(void), unsigned long time, int once ){
	if (time >= MAX_TICK ){
		dupaTimer("MAX_TICK - too much time");
		return -1;
	}
	return privAddEl(fun, time, once);


}
void startTimer( int ID ){
	element *wsk;
	wsk = timerList;
	while(wsk->ID != ID){
		if(wsk->next == NULL){
			//mamy problem (start)!
			return;
		}
		wsk = wsk->next;
	}

	wsk->accTime = (tick + wsk->time);
	wsk->Off = 0;

	dupaTimer("Started timer ID\n");
	dupaTimerInt(ID);
	return;
}
void stopTimer( int ID ){
	element *wsk;
	wsk = timerList;
	while(wsk->ID != ID){
		if(wsk->next == NULL){
			//mamy problem (stop)!
			return;
		}
		wsk = wsk->next;
	}
	wsk->Off = 1;
	dupaTimer("Stopped timer ID\n");
	dupaTimerInt(ID);
	return;
}

void delTimer( int ID ){
	element *wsk, *del;
	wsk = timerList;

	while(wsk->next != NULL){
		if (wsk->next->ID == ID){
			del = wsk->next;
			wsk->next = del->next;
			free(del);
			dupaTimer("Timer removed ID\n");
			dupaTimerInt(ID);
		}else{
			wsk=wsk->next;
		}
	}
	return;
}

void changeTimer( int ID, unsigned long time ){
	element *wsk;
	wsk = timerList;
	while(wsk->ID != ID){
		if(wsk == NULL){
			//mamy problem (start)!
			return;
		}

		wsk = wsk->next;
	}
	wsk->time = time;
	wsk->accTime = (tick + wsk->time) % MAX_TICK;
	dupaTimer("Started timer ID\n");
	dupaTimerInt(ID);
	return;
}

int isTimerOn(int ID){
	element *wsk;
	wsk = timerList;
	dupaTimer("isOnTimer? ID\n");
	dupaTimerInt(ID);

	while(wsk->ID != ID){
		if(wsk->next == NULL){
			//mamy problem (start)!
			return 0;
		}
	wsk = wsk->next;
	}

	if (wsk->Off == 1){
		return 0;
	}else if (wsk->Off == 0){
		return 1;
	}

	return 0;

}


int privAddEl( void (*fun)(void), unsigned long time, int once ){
	element *wsk, *nowy;
	wsk = timerList;
	if(wsk->ID == NULL){
		wsk->fun = fun;
		wsk->ID = nrEl;
		nrEl++;
		wsk->Off = 1;
		wsk->Once = once;
		wsk->time = time;
		wsk->accTime = (tick + wsk->time) % MAX_TICK;
		wsk->next=NULL;
		dupaTimer("bdd first timer\n");
	}else{

		while(wsk->next != NULL){
			wsk = wsk->next;

		}

		nowy = (element*)malloc(sizeof(element));
		wsk->next = nowy;
		nowy->ID = nrEl;
		nowy->fun = fun;
		nrEl++;
		nowy->time = time;
		nowy->accTime = (tick + wsk->time) % MAX_TICK;
		nowy->Off = 1;
		nowy->Once = once;
		nowy->next = NULL;
		dupaTimer("add next timer \n");

	}
	return (nrEl -1 );
}

void privCheck(void){
	/*element *wsk;
	wsk = timerList;
	while(wsk != NULL){
		if(wsk->accTime == tick){
			if (wsk->Off != 1){
				wsk->fun();
				wsk->accTime = (wsk->accTime + wsk->time ) % MAX_TICK;
				if( wsk->Once == 1 ) wsk->Off = 1;
				dupaTimer("Check timer");
				dupaTimerInt(wsk->ID);
			}
		}
		wsk = wsk->next;

	}
	*/
	return;
}

void privShow(void){
	/*
	element *wsk;
	wsk = timerList;
	while(wsk->next != NULL){
		dupaTimer(" timer: ");
		dupaTimer(wsk->ID);
		dupaTimer(wsk->time);
		dupaTimer(wsk->accTime);
		dupaTimer(wsk->Off);
		dupaTimer(wsk->Once);

		wsk = wsk->next;
	}
	*/
	return;
}

/////////////////////////////////////////////
/////////////////////////////////////////////
/////////////////////////////////////////////

void dupaTimer(char *string){

	//while (*string != '\0') usart_putchar(&AVR32_USART1, *string++);

}

void dupaTimerInt( int n ){
/*
	char string[11];
	int i = 10;
	string[i] = '\0';
	do{
		string[--i] = '0' + n%10;
		n /= 10;
	}while(n);
	dupaTimer(string);
*/

}
